#include "../include/soundplayer.h"
#include <stdlib.h>
#include <unistd.h>
#include <neaacdec.h>

environment_t env;

int refill_buffer(FILE* input, unsigned char *b, int b_size, int bytes_remaining){
	//moves remaining bytes to beginning of buffer
	//fills remaining space from
	int i = bytes_remaining; //make a copy for looping
	while (--i) b[bytes_remaining - i] = b[b_size - i];

	return fread(b + bytes_remaining, 1, b_size - bytes_remaining, input);
}

void play_aac(FILE* input){

	if (env->status != SP_IDLE) goto END;
	env->status = SP_PLAY;

	//declarations
	struct NeAACDecFrameInfo hInfo;
	short* obuffer;
	int buffer_size = FAAD_MIN_STREAMSIZE*8;         //8 channels
	unsigned long index = 0; //position in file

	//preparing input buffer (cache file or read from pipe)
	unsigned char* buffer = (unsigned char*) malloc(env->size);
	fread(buffer, 1, env->size, input);

	//check the capabilities of the decoder
	env->message("Decoder Capabilities are %lu\n", NeAACDecGetCapabilities());

	NeAACDecHandle hAac = NeAACDecOpen();

	//Configure the decoder
	NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(hAac);
	conf->defObjectType = 2;         //aac "MAIN"
	conf->defSampleRate = 44100;
	conf->outputFormat = 1;
	conf->downMatrix = 1;
	NeAACDecSetConfiguration(hAac, conf);         //set the stuff

	// Initialise the library using one of the initialization functions
	unsigned long samplerate;
	unsigned char channels;
	index = NeAACDecInit(hAac, buffer, 32768, &samplerate, &channels);
	env->message("samplerate = %lu\tchannels = %i\tNeAACDecInit return = %lu\n", samplerate, channels, index);

	if (index != 0) {
		env->message("Decoder failed to initialize!\n");
		env->status = SP_ERROR;
	}

	int runonce = 1;
	do {
		while ((env->size - index) > 0 ) {

				//handle all statuses in 3 lines
				if (env->status > SP_PLAY) {
					while (env->status == SP_PAUSE) sleep(1);
					if (env->status > SP_PAUSE) goto CLEANUP;
				}

				obuffer = NeAACDecDecode(hAac, &hInfo, buffer+index, buffer_size);

				//analyze once
				if (runonce) {
					runonce--;
					if(FLAGUNSET(SP_OVERRIDE_HERTZ)) env->rate = hInfo.samplerate;
					if(FLAGUNSET(SP_OVERRIDE_CHANNEL)) env->channels = hInfo.channels;
				}

				index += hInfo.bytesconsumed;
				if ((hInfo.error == 0) && (hInfo.samples > 0)){
					pcm_output_write(obuffer, hInfo.samples/hInfo.channels);
				}
				else if (hInfo.error != 0) {
					env->message("%s\n", NeAACDecGetErrorMessage(hInfo.error));
				}
		}
		index = 0; //reset index in case buffer refills
	} while (refill_buffer(input, buffer, env->size, buffer_size - index));

	CLEANUP:
	NeAACDecClose(hAac);
	free(buffer);
	env->status = SP_IDLE;

	END:
		;
}
